﻿using System;
using Autofac;
using Zinnia.Common;
using Zinnia.Kernel.Inject.Config;
using Zinnia.Kernel.Inject.Core;

namespace Zinnia.Kernel.Inject
{
    /// <summary>
    /// 默认依赖注入器端口
    /// </summary>
    public sealed class DependencyInjectHub : IDependencyInjectHub
    {
        private static MiniLogger logger = LoggerHelper.GetMiniLogger("boot");
        private static IContainer _dependencyContainer;
        public DependencyInjectHub()
        {
        }
        public void Dispose()
        {
            _dependencyContainer.Dispose();
        }

        public void Init(bool isManual = false)
        {
            var builder = new ContainerBuilder();
            //外部依赖注入注册[读取配置文件]
            foreach (var dependency in DependencyInjectRegisterConfigManager.GetDependencyInjectRegisterConfigContainer().DependencyInjectRegisterConfigs)
            {
                bool isCreateInstanceSuccess = true;
                try
                {
                    AssemblyHelper.CreateInstance<IDependencyInjectRegister>(dependency.Assembly, dependency.Type)
                        .Register(builder);
                }
                catch (Exception ex)
                {
                    //logger.WriteLogAsync($"外部依赖注入异常" + ex); 有问题
                    isCreateInstanceSuccess = false;
                    logger.Write(ex.ToString());
                }
                finally
                {
                    if (isCreateInstanceSuccess)
                    {
                        logger.Write($"Load assembly {dependency.Assembly} and create instance {dependency.Type} success");
                    }
                }
            }
            //单例
            builder.RegisterAssemblyTypes(AssemblyHelper.GetCurrentDomainAssembly())
           .Where(t => typeof(ISingleDependencyInject).IsAssignableFrom(t) && typeof(ISingleDependencyInject) != t)
           .AsImplementedInterfaces()
           .SingleInstance();
            //多例
            builder.RegisterAssemblyTypes(AssemblyHelper.GetCurrentDomainAssembly())
                .Where(t => typeof(ITransientDependencyInject).IsAssignableFrom(t) && typeof(ITransientDependencyInject) != t)
                .AsImplementedInterfaces()
                .InstancePerDependency();
            //工作单元单例
            builder.RegisterAssemblyTypes(AssemblyHelper.GetCurrentDomainAssembly())
                .Where(t => typeof(IUintOfWorkDependencyInject).IsAssignableFrom(t) && typeof(IUintOfWorkDependencyInject) != t)
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope();
            _dependencyContainer = builder.Build();
        }

        public void UnLoad()
        {
            Dispose();
        }

        public T Resolve<T>()
        {
            return _dependencyContainer.Resolve<T>();
        }
    }
}
